package com.financial.service.yspay.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.financial.service.yspay.connector.FinancialPlatformPayFegin;
import com.financial.service.yspay.constants.FinancialYsPayPaymentReceiptEnumConstants;
import com.financial.service.yspay.dao.FinancialYsPayPaymentReceiptDao;
import com.financial.service.yspay.domain.FinancialYsPayPaymentReceiptDO;
import com.financial.service.yspay.dto.FinancialYsPayDTO;
import com.financial.service.yspay.mq.FinancialYsPayReturnMQConfig;
import com.financial.service.yspay.service.FinancialYsPayBuildRequestParaService;
import com.financial.service.yspay.service.FinancialYsPayPaymentService;
import com.financial.service.yspay.service.FinancialYsPayVerifyJsonSignService;
import com.financial.service.yspay.utils.*;
import com.financial.service.yspay.utils.apiresult.ApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: WANGNING
 * @Email wyn20140226@aliyun.com
 * @Date: 2019/6/4 18:45
 * @Des
 */
@Service
public class FinancialYsPayPaymentServiceImpl implements FinancialYsPayPaymentService {
    private static Logger log = LoggerFactory.getLogger(FinancialYsPayPaymentServiceImpl.class);
    public static final String BANK_ACCOUNT_TYPE = "bankAccountType";
    @Autowired
    private FinancialPlatformPayFegin platformPayFegin;
    @Autowired
    private FinancialYsPayBuildRequestParaService ysBuildRequestParaService;
    @Autowired
    private FinancialYsPayVerifyJsonSignService ysVerifyJsonSignService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private Producer producer;
    @Autowired
    private FinancialYsPayPaymentReceiptDao yspaymentReceiptDao;

    @Override
    public Map<String, Object> payment(Map<String, Object> mapParams) {
        log.info("调用银盛代付接口初始参数" + JSON.toJSONString(mapParams));
        Object temp = "";
        String totalAmount = "";
        String platfromMarking = mapParams.get("platfromMarking").toString();
        String platfromId = mapParams.get("platfromId").toString();
        String paymentType = mapParams.get("payment_type").toString();
        String channelsId = mapParams.get("channelsId").toString();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        temp = mapParams.get("outTradeNo");
        String outTradeNo = temp != null ? temp.toString() : null;
        //01代表余额代付 02代表积分代付
        if (paymentType.equals("01")) {
            temp = mapParams.get("balancePaymentAmount");
            totalAmount = temp != null ? temp.toString() : null;
        } else if (paymentType.equals("02")) {
            temp = mapParams.get("integralAmount");
            totalAmount = temp != null ? temp.toString() : null;
        }
        temp = mapParams.get("subject");
        String subject = temp != null ? temp.toString() : null;
        temp = mapParams.get("bankName");
        String bankName = temp != null ? temp.toString() : null;
        temp = mapParams.get("bankCity");
        String bankCity = temp != null ? temp.toString() : null;
        temp = mapParams.get("bankAccountNo");
        String bankAccountNo = temp != null ? temp.toString() : null;
        temp = mapParams.get("bankAccountName");
        String bankAccountName = temp != null ? temp.toString() : null;
        temp = mapParams.get("bankAccountType");
        String bankAccountType = temp != null ? temp.toString() : null;
        temp = mapParams.get("bankCardType");
        String bankCardType = temp != null ? temp.toString() : null;
        //根据订单号截取商户日期
        String shopdate = outTradeNo.substring(0, 8);
        Map<String, Object> biz_contentMap = new HashMap<String, Object>();
        biz_contentMap.put("out_trade_no", outTradeNo);
        //1.当商户号为空时，默认将partner_id,作为商户号 2.如果提现的商户号和合作商户号不一致则需要检查机构信息
//			biz_contentMap.put("merchant_usercode", m.getMerchant_usercode());
        biz_contentMap.put("shopdate", shopdate);
        //业务代码 生产 2010022   测试：01000018
        biz_contentMap.put("business_code", "2010022");
        biz_contentMap.put("currency", "CNY");
        biz_contentMap.put("total_amount", new BigDecimal(totalAmount));
        biz_contentMap.put("subject", subject);
        //银行名称，为了保证代付交易成功，银行名称最好具体到分行
        biz_contentMap.put("bank_name", bankName);
        //开户行所在城市
        biz_contentMap.put("bank_city", bankCity);
        //银行帐号，注：当bank_account_type为对公账户时，该属性字段长度可以为String(1,32)
        biz_contentMap.put("bank_account_no", bankAccountNo);
        //银行帐号用户名
        biz_contentMap.put("bank_account_name", bankAccountName);
        //收款方银行账户类型，此处必填
        //corporate :对公账户;personal:对私账户
        biz_contentMap.put("bank_account_type", bankAccountType);
        //支持卡类型，此处必填 	debit:借记卡;credit:信用卡 unit:单位结算卡
        biz_contentMap.put("bank_card_type", bankCardType);
        //根据平台支付通道类型，平台应用标识获取具体配置参数
        String ysBusiness = platformPayFegin.getYSBusiness(platfromId, channelsId);
        String parse = String.valueOf(JSON.parse(ysBusiness));
        FinancialYsPayDTO ysPayDTO = JSON.parseObject(parse, FinancialYsPayDTO.class);
        redisUtils.setKey(outTradeNo, JsonUtils.objectToJson(mapParams), 60 * 30);
        //封装公共参数以及业务参数
        Map<String, String> paramsMap = new HashMap<>();
        //加急
        paramsMap.put("method", "ysepay.df.single.quick.accept");
        paramsMap.put("partner_id", ysPayDTO.getPARTNER_ID_DF());
        paramsMap.put("timestamp", DateUtils.getNowTimeStr());
        paramsMap.put("charset", ysPayDTO.getDEFAULT_CHARSET());
        paramsMap.put("sign_type", ysPayDTO.getSIGN_ALGORITHM());
        paramsMap.put("version", ysPayDTO.getVERSION());
        paramsMap.put("notify_url", "");
        paramsMap.put("biz_content", JSON.toJSONString(biz_contentMap));
        Map<String, Object> resultStr = null;
        try {
            //签名
            Map<String, String> sPara = ysBuildRequestParaService.buildRequestParaDF(paramsMap, ysPayDTO);
            //发起请求
            log.info("签名完成的参数：{}", sPara);
            String returnString = HttpUtils.httpsSend(ysPayDTO.getYSEPAY_GATEWAY_URL_DF(), sPara);
            log.info("银盛非一清待打款接口返回信息:" + returnString);
            resultMap = (Map) JSON.parse(returnString);
            boolean verifyResult = false;
            int yscount = returnString.indexOf("ysepay_df_single_quick_accept_response");
            String str = returnString.substring(yscount);
            str = str.replace("ysepay_df_single_quick_accept_response", "");
            str = str.substring(2, str.length() - 1);
            verifyResult = ysVerifyJsonSignService.verifyJsonSign(resultMap.get("sign").toString(), str, "utf-8", ysPayDTO);
            resultStr = JsonUtils.jsonToMap(str);
            log.info("YsPaymentServiceImpl -------------------payment" + "校验是否成功" + verifyResult + resultMap);
            //保存余额代付回执信息
            FinancialYsPayPaymentReceiptDO yspaymentReceiptDO = new FinancialYsPayPaymentReceiptDO();
            yspaymentReceiptDO.setPaymentType(paymentType);
            yspaymentReceiptDO.setResponseType(FinancialYsPayPaymentReceiptEnumConstants.ENUM_RESPONSETYPE_SYNC);
            yspaymentReceiptDO.setOutTradeNo(outTradeNo);
            yspaymentReceiptDO.setContent(str);
            yspaymentReceiptDO.setGmtModified(new Date());
            yspaymentReceiptDO.setGmtCreate(new Date());
            yspaymentReceiptDO.setPlatformnum(platfromMarking);
            yspaymentReceiptDO.setIsDelete(FinancialYsPayPaymentReceiptEnumConstants.ENUM_ISDELETE_UNDEL);
            yspaymentReceiptDao.save(yspaymentReceiptDO);

        } catch (Exception e) {
            e.printStackTrace();
            log.error("银盛非一清待打款接口" + e.toString());
        } finally {
            return resultStr;
        }
    }

    @Override
    public void asyncPayment(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> paramMap = ParamUtils.getParamMap(request);
        log.info("银盛代付异步接口回执参数为" + JsonUtils.objectToJson(paramMap));
//        log.info("银盛代付异步接口回执参数为" + JSONUtils.objectToJson(paramMap));
        String outTradeNo = paramMap.get("out_trade_no");
        //根据订单号从redis中获取参数 平台标识 平台名称
        Object obj = redisUtils.getValue(outTradeNo);
        if (null == obj) {
            ApiResult.failure("订单号不正确");
        }
        Map<String, Object> value = JsonUtils.jsonToMap((String) obj);
        PrintWriter writer = null;
        if (null != value) {
            String platfromMarking = value.get("platfromMarking").toString();
            String platfromId = value.get("platfromId").toString();
            String paymentType = value.get("payment_type").toString();
            String channelsId = value.get("channelsId").toString();
            try {
                String ysBusiness = platformPayFegin.getYSBusiness(platfromId, channelsId);
                String parse = String.valueOf(JSON.parse(ysBusiness));
                FinancialYsPayDTO ysPayDTO = JSON.parseObject(parse, FinancialYsPayDTO.class);

                Message message = null;
                writer = response.getWriter();
                boolean verifyResult = ysVerifyJsonSignService.verifySign(paramMap, ysPayDTO);
                log.error("银盛异步待打款回執信息" + verifyResult);
                paramMap.put("platfromMarking", platfromMarking);
                paramMap.put("paymentType", paymentType);
                paramMap.put("platfromId", platfromId);
                //保存异步回执信息
                saveAsyncWithdrawal(paramMap);
                // 状态
                if (verifyResult) {// 验证成功
                    //根据支付通道类型判断往哪个中心发送异步通知
                    if (paymentType.equals("01")) {
                        message = new Message(FinancialYsPayReturnMQConfig.BALANCE_TOPIC, FinancialYsPayReturnMQConfig.BLANCEPAY, JsonUtils.objectToJson(paramMap).getBytes());
                        // 发送Mq
                        producer.send(message);
                        log.error("银盛异步待打款回執发送消息" + new String(message.getBody()));
                        writer.print("success");
                        //02代表积分代付
                    } else if (paymentType.equals("02")) {
                        message = new Message(FinancialYsPayReturnMQConfig.INTEGTAL_TOPIC, FinancialYsPayReturnMQConfig .INTEGRAL, JsonUtils.objectToJson(paramMap).getBytes());
                        // 发送Mq
                        producer.send(message);
                        log.error("银盛异步待打款回執发送消息" + new String(message.getBody()));
                        writer.print("success");
                    }

                } else {// 验证失败
                    log.error("银盛异步待打款回執错误消息" + new String(message.getBody()));
                    writer.print("fall");
                }
            } catch (Exception e) {
                log.error("银盛异步待打款回执接口调用失败！", e.getMessage());
                e.printStackTrace();
            } finally {
                if (writer != null) {
                    writer.close();
                }
            }

        }


    }

    @Override
    public Map<String, Object> paymentQuery(Map<String, Object> mapParams) {
        log.info("YsPaymentServiceImpl ----------------paymentQuery" + JsonUtils.objectToJson(mapParams));
        String outTradeNo = mapParams.get("out_trade_no").toString();
        String platfromId = mapParams.get("platfromId").toString();
        //String paymentType = mapParams.get("payment_type").toString();
        String channelsId = mapParams.get("channelsId").toString();
        String shopdate = mapParams.get("shopdate").toString();
        if (StringUtils.isEmpty(outTradeNo) || StringUtils.isEmpty(shopdate) || StringUtils.isEmpty(platfromId)
                || StringUtils.isEmpty(channelsId)) {
            return null;
        }
        Map<String, Object> resultMap = null;
        Map<String, Object> bizContentMap = new HashMap<String, Object>();
        String str = "";
        //根据平台支付通道类型，平台应用标识获取具体配置参数
        String ysBusiness = platformPayFegin.getYSBusiness(platfromId, channelsId);
        String parse = String.valueOf(JSON.parse(ysBusiness));
        FinancialYsPayDTO ysPayDTO = JSON.parseObject(parse, FinancialYsPayDTO.class);
        redisUtils.setKey(outTradeNo, mapParams, 60 * 30);
        //封装公共请求参数Map
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("method", "ysepay.df.single.query");
        paramMap.put("partner_id", ysPayDTO.getPARTNER_ID_DF());
        paramMap.put("timestamp", DateUtils.getNowTimeStr());
        paramMap.put("charset", ysPayDTO.getDEFAULT_CHARSET());
        paramMap.put("sign_type", ysPayDTO.getSIGN_ALGORITHM());
        paramMap.put("version", ysPayDTO.getVERSION());

        bizContentMap.put("out_trade_no", outTradeNo);
        bizContentMap.put("shopdate", shopdate);
        paramMap.put("biz_content", JSON.toJSONString(bizContentMap));
        Map<String, Object> jsonMap = null;
        //签名信息
        try {
            Map<String, String> sPara = ysBuildRequestParaService.buildRequestParaDF(paramMap, ysPayDTO);
            String returns = HttpUtils.httpsSend(ysPayDTO.getYSEPAY_GATEWAY_URL_DF_SEARCH(), sPara);
            resultMap = (Map) JSON.parse(returns);
            Object obj = resultMap.get("ysepay_df_single_query_response");
            boolean verifyResult = false;
            if (obj != null) {
                int yscount = returns.toString().indexOf("ysepay_df_single_query_response");
                str = returns.substring(yscount);
                str = str.replace("ysepay_df_single_query_response", "");
                str = str.substring(2, str.length() - 1);
                verifyResult = ysVerifyJsonSignService.verifyJsonSign(resultMap.get("sign").toString(), str, "utf-8", ysPayDTO);
                log.info("验证签名信息" + verifyResult);
                log.info("银盛代付查询返回信息" + str);
                //本地数据库保存银盛代付查询返回信息
                jsonMap = JsonUtils.jsonToMap(str);
                jsonMap.put("outTradeNo", outTradeNo);
                //保存代付查询结果集
                //savePaymentQuery(jsonMap);
                return jsonMap;
            }
        } catch (IOException e) {
            log.error("银盛代付查询接口" + e.getMessage());
            e.printStackTrace();
        } catch (IllegalAccessException e1) {
            log.error("银盛代付查询接口" + e1.getMessage());
            e1.printStackTrace();
        } finally {
            return jsonMap;
        }
    }

    private void saveAsyncWithdrawal(Map<String, String> paramMap) {
        FinancialYsPayPaymentReceiptDO yspaymentReceiptDO = new FinancialYsPayPaymentReceiptDO();
        try {
            String out_trade_no = paramMap.get("out_trade_no");
            String platfromMarking = paramMap.get("platfromMarking");
            String paymentType = paramMap.get("paymentType");
            yspaymentReceiptDO.setOutTradeNo(out_trade_no);
            yspaymentReceiptDO.setResponseType("2");
            yspaymentReceiptDO.setIsDelete("1");
            yspaymentReceiptDO.setContent(JsonUtils.objectToJson(paramMap));
            yspaymentReceiptDO.setGmtModified(new Date());
            yspaymentReceiptDO.setGmtCreate(new Date());
            yspaymentReceiptDO.setPlatformnum(platfromMarking);
            yspaymentReceiptDO.setPaymentType(paymentType);
            yspaymentReceiptDao.save(yspaymentReceiptDO);
        } catch (Exception e) {
            log.error("代付异步回执日志记录保存失败" + yspaymentReceiptDO.toString());
        }

    }

}
